/**
 * PopUpManager
 * 弹出管理器
 */
//
enum UIPopDir {
  Center = 0,
  Bottom
}
class PopUpManager {

  private static _instance: PopUpManager;

  private stageChangeDisplay: egret.DisplayObjectContainer;
  private stageChangeLabel: eui.Label;
  private stageChangeImg: eui.Image;
  private itemGetDisplay: egret.DisplayObjectContainer;
  loadingLayer: egret.DisplayObject;

  constructor() {
    Logger.assert(!PopUpManager._instance, "Create popUp manager multiple times");
  }

  public static get instance(): PopUpManager {
    if (!PopUpManager._instance) {
      PopUpManager._instance = new PopUpManager();
    }
    return PopUpManager._instance;
  }

  init(container: egret.DisplayObjectContainer, modalColor: number = 0x000000, modalAlpha: number = 0.8): boolean {
    this.container = container;
    this.modalAlpha = modalAlpha;
    this.modalColor = modalColor;
    this.eventDispatcher = new egret.EventDispatcher();
    this.popUpDataList = [];
    this.popUpList = [];
    this.invalidateModalFlag = false;
    return true;
  }

  private container: egret.DisplayObjectContainer;
  private popUpDataList: PopUpData[];
  private popUpList: egret.DisplayObject[];
  private eventDispatcher: egret.EventDispatcher;

  modalAlpha: number;

  modalColor: number;
  getModalColor(): number {
    return this.modalColor;
  }

  setModalColor(a: number) {
    this.modalColor = a;
  }

  alert(msg: string, title: string = "") {
    // let panel = new AlertPanel();
    // panel.alert(msg);
    // panel.setTitle(title);
    // this.popup(panel);
  }

  toast(msg: String, timeLong: number) {

  }

  /**
    * 有缓动的弹出。(可重复无效)
    * 返回弹出的实例
    */
  public showView(params: { className: any, dir: UIPopDir, modal: boolean }, ...args): any {
    Logger.debug("popup,length:", this.popUpList.length, this.popUpDataList.length);
    if (!params.className)
      return null;
    let poup = new params.className(...args);
    poup.left = 0;
    poup.top = 0;
    poup.right = 0;
    poup.bottom = 0;
    this.popup(poup, params.dir, params.modal);
    return poup;
  }

  /**
    * 有缓动的弹出。（可重复弹出）
    *  
    */
  public popup(popup: egret.DisplayObject, dir?: UIPopDir, modal?: boolean) {
    let f = (event: PopUPEvent) => {
      popup.scaleX = 0.3;
      popup.scaleY = 0.3;
      popup.alpha = 0.2;
      egret.Tween.get(popup).to({ scaleX: 1.0, scaleY: 1.0, alpha: 1 }, 200, egret.Ease.backInOut);
      this.removeEventListener(EventConst.Popup.AddPopup, f, this);
    };
    this.addEventListener(EventConst.Popup.AddPopup, f, this);
    this.addPopUp(popup, dir, modal);
  }

  public addPopUp(popUp: egret.DisplayObject, dir: UIPopDir = UIPopDir.Center, modal: boolean = true) {
    let container = this.container;
    let data = this.findPopUpData(popUp);
    if (data) {
      data.modal = modal;
      popUp.removeEventListener(egret.Event.REMOVED_FROM_STAGE, this.onRemoved, this);
    } else {
      data = new PopUpData(popUp, modal);
      this.popUpDataList.push(data);
      this.popUpList.push(popUp);
    }
    container.addChild(popUp);
    switch (dir) {
      case UIPopDir.Center: {
        this.centerPopUp(popUp);
        break;
      }
      case UIPopDir.Bottom: {
        this.bottomPopUp(popUp);
        break;
      }
    }

    if ("isPopUp" in popUp)
      popUp["isPopUp"] = true;
    if (modal) {
      this.invalidateModal();
    }

    popUp.once(egret.Event.REMOVED_FROM_STAGE, this.onRemoved, this);

    this.dispatchPopUpEvent(EventConst.Popup.AddPopup, popUp, modal);
  }

  private onRemoved(event: egret.Event) {
    if ("isPopUp" in event.target) {
      event.target["isPopUp"] = false;
    }
    let index = this.popUpList.indexOf(event.target);
    if (index >= 0) {
      this.popUpList.splice(index, 1);
      this.popUpDataList.splice(index, 1);
      this.invalidateModal();
    }
  }

  public hasPop(name: string) {
    for (let i = 0; i < this.popUpList.length; i++) {
      if (name.indexOf(this.popUpList[i].name) > -1) {
        return true;
      }
    }
    return false;
  }

  removePopUp(popUp: egret.DisplayObject) {
    if (popUp && popUp.parent && this.findPopUpData(popUp)) {
      popUp.anchorOffsetX = 0;
      popUp.anchorOffsetY = 0;
      GameUtils.removeFromParent(popUp);
    }
    this.dispatchPopUpEvent(EventConst.Popup.RemovePopup, popUp);
  }

  centerPopUp(popup: egret.DisplayObject) {
    let parent = popup.parent;
    if (parent) {

      popup.anchorOffsetX = popup.width * 0.5;
      popup.x = ((parent.width - popup.width) >> 1) + popup.anchorOffsetX;
      popup.y = ((parent.height - popup.height) >> 1) + popup.anchorOffsetY;
    }
  }
  bottomPopUp(popup: egret.DisplayObject, isFull?: boolean) {
    let parent = popup.parent;
    if (parent) {

      popup.anchorOffsetX = popup.width * 0.5;
      popup.anchorOffsetY = popup.height;
      popup.x = ((parent.width - popup.width) >> 1) + popup.anchorOffsetX;
      popup.y = (parent.height - popup.height) + popup.anchorOffsetY;
    }
  }

  bringToFront(popUp: egret.DisplayObject) {
    let data = this.findPopUpData(popUp);
    if (data && popUp.parent) {
      let uiStage = (popUp.parent);

      this.container.setChildIndex(popUp, this.container.numChildren - 1);
      this.invalidateModal();
    }

    this.dispatchPopUpEvent(EventConst.Popup.BringToFront, popUp);
  }

  private findPopUpData(popUp: egret.DisplayObject) {
    let list = this.popUpDataList;
    let length = list.length;
    for (let i = 0; i < length; i++) {
      let data = list[i];
      if (data.popUp === popUp)
        return data;
    }
    return null;
  }

  private invalidateModalFlag: boolean = false;

  private invalidateModal() {
    if (!this.invalidateModalFlag) {
      this.invalidateModalFlag = true;

      let container = this.container;
      if (container && container.stage) {
        container.stage.addEventListener(egret.Event.ENTER_FRAME, this.validateModal, this);
        container.stage.addEventListener(egret.Event.RENDER, this.validateModal, this);
        container.stage.invalidate();
      }
    }
  }

  private validateModal() {
    this.invalidateModalFlag = false;
    let container = this.container;
    if (container && container.stage) {
      container.stage.removeEventListener(egret.Event.ENTER_FRAME, this.validateModal, this);
      container.stage.removeEventListener(egret.Event.RENDER, this.validateModal, this);
      this.updateModal();
    }
  }

  private modalMask: eui.Rect;
  private updateModal() {
    let container = this.container;
    let found = false;
    let i: number;
    for (i = container.numChildren - 1; i >= 0; i--) {
      let element = container.getChildAt(i);
      let data = this.findPopUpData(element);
      if (data && data.modal) {
        found = true;
        break;
      }
    }
    if (found) {
      if (!this.modalMask) {
        this.modalMask = new eui.Rect(container.width, container.height);
        this.modalMask.touchEnabled = true;
      }
      this.modalMask.fillColor = this.modalColor;
      this.modalMask.alpha = this.modalAlpha;
      if (this.modalMask.parent === container) {
        if (container.getChildIndex(this.modalMask) < i) {
          i--;
        }
        container.setChildIndex(this.modalMask, i);
      } else {
        container.addChildAt(this.modalMask, i);
      }
    } else if (this.modalMask && this.modalMask.parent === container) {
      container.removeChild(this.modalMask);
    }
  }

  addEventListener(type: string, listener: Function, thisObject: any, useCapture?: boolean, priority?: number) {
    this.eventDispatcher.addEventListener(type, listener, this, useCapture, priority);
  }

  removeEventListener(type: string, listener: Function, thisObject: any, useCapture: boolean = false) {
    this.eventDispatcher.removeEventListener(type, listener, this, useCapture);
  }

  private dispatchPopUpEvent(type: string, popUp?: egret.DisplayObject, modal?: boolean) {
    this.eventDispatcher.dispatchEvent(new PopUPEvent(type, false, false, popUp, modal));
  }
}

class PopUpData {
  popUp: egret.DisplayObject;
  modal: boolean;

  constructor(popUp: egret.DisplayObject, modal: boolean) {
    this.popUp = popUp;
    this.modal = modal;
  }
}

class PopUPEvent extends egret.Event {
  popUp: egret.DisplayObject;
  modal: boolean;

  constructor(type: string, bubbles?: boolean, cancelable?: boolean, popUp?: egret.DisplayObject, modal?: boolean) {
    super(type, bubbles, cancelable);
    this.popUp = popUp;
    this.modal = modal;
  }
}
